package com.cjd.common.listener

import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.cjd.common.utils.LogUtils

/**
 * @Author chenjidong
 * @email 374122600@qq.com
 * created 2017/6/19.
 * description 根据 LayoutManager 监听滚动 {@link OnRecyclerLoadMoreListener}
 */
open class OnRecyclerLoadMoreScrollListener : RecyclerView.OnScrollListener(),
    OnRecyclerLoadMoreListener {

    /**
     * layoutManager的类型（枚举）
     */
    private var layoutManagerType: LAYOUT_MANAGER_TYPE? = null

    /**
     * 最后一个的位置
     */
    private var lastPositions: IntArray? = null

    /**
     * 最后一个可见的item的位置
     */
    private var lastVisibleItemPosition: Int = 0
    private var firstVisibleItemPosition: Int = 0

    /**
     * 当前滑动的状态
     */
    private var currentScrollState: Int = 0
    /**
     * 滚动到底部次数  滚动到顶部就会清零
     */
    private var rollBottomCount = 0
    private var rollTopCount = 0
    private var dy = 0
    private var dx = 0

    enum class LAYOUT_MANAGER_TYPE {
        LINEAR,
        GRID,
        STAGGERED_GRID
    }

    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        val layoutManager = recyclerView.layoutManager
        if (layoutManagerType == null) {
            if (layoutManager is GridLayoutManager)
                layoutManagerType = LAYOUT_MANAGER_TYPE.GRID
            else if (layoutManager is LinearLayoutManager)
                layoutManagerType = LAYOUT_MANAGER_TYPE.LINEAR
            else if (layoutManager is StaggeredGridLayoutManager)
                layoutManagerType = LAYOUT_MANAGER_TYPE.STAGGERED_GRID
            else
                throw RuntimeException(
                    "Unsupported LayoutManager used. Valid ones are LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager"
                )
        }
        when (layoutManagerType) {
            LAYOUT_MANAGER_TYPE.LINEAR -> if (layoutManager is LinearLayoutManager) {
                lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()
                firstVisibleItemPosition = layoutManager.findFirstCompletelyVisibleItemPosition()
            }
            LAYOUT_MANAGER_TYPE.GRID -> if (layoutManager is GridLayoutManager) {
                lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()
                firstVisibleItemPosition = layoutManager.findFirstCompletelyVisibleItemPosition()
            }
            LAYOUT_MANAGER_TYPE.STAGGERED_GRID -> if (layoutManager is StaggeredGridLayoutManager) {
                val staggeredGridLayoutManager = layoutManager as StaggeredGridLayoutManager?
                if (lastPositions == null) {
                    lastPositions = IntArray(staggeredGridLayoutManager!!.spanCount)
                }
                staggeredGridLayoutManager!!.findLastVisibleItemPositions(lastPositions)
                lastVisibleItemPosition = findMax(lastPositions!!)
            }
        }
        this.dy = dy
        this.dx = dx
    }

    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
        currentScrollState = newState
        val layoutManager = recyclerView.layoutManager
        val visibleItemCount = layoutManager!!.childCount
        val totalItemCount = layoutManager.itemCount
        if (visibleItemCount > 0 && currentScrollState == RecyclerView.SCROLL_STATE_IDLE) {
            if (lastVisibleItemPosition >= totalItemCount - 1) {
                rollTopCount = 0
                rollBottomCount += 1
                LogUtils.d("Loading More $rollBottomCount top:$rollTopCount")
                onLoadMore(rollBottomCount)
            } else if (firstVisibleItemPosition == 0) {
                rollTopCount += 1
                rollBottomCount = 0
                LogUtils.d("scroll top $rollTopCount bottom:$rollBottomCount")
                onRollTop(rollTopCount)
            }
        }

        if (lastVisibleItemPosition >= totalItemCount - 1) {
            onRollBottom()
        }
    }

    override fun onRollBottom() {

    }

    override fun onLoadMore() {

    }

    override fun onLoadMore(rollBottomCount: Int) {
        super.onLoadMore(rollBottomCount)
        onLoadMore()
    }

    private fun findMax(lastPositions: IntArray): Int {
        var max = lastPositions[0]
        for (value in lastPositions) {
            if (value > max)
                max = value
        }
        return max
    }
}